home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Networking / GetSetOptions / GetSetOptions.c next >
Encoding:
Text File  |  2000-09-28  |  14.5 KB  |  506 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        GetSetOptions.c
  3.  
  4.     Contains:    Sample for getting and setting options using the various
  5.                 option management routines.
  6.  
  7.     Written by: Quinn "The Eskimo!"    
  8.  
  9.     Copyright:    Copyright © 1997-1999 by Apple Computer, Inc., All Rights Reserved.
  10.  
  11.                 You may incorporate this Apple sample source code into your program(s) without
  12.                 restriction. This Apple sample source code has been provided "AS IS" and the
  13.                 responsibility for its operation is yours. You are not permitted to redistribute
  14.                 this Apple sample source code as "Apple sample source code" after having made
  15.                 changes. If you're going to re-distribute the source, we require that you make
  16.                 it clear in the source that the code was descended from Apple sample source
  17.                 code, but that you've made changes.
  18.  
  19.     Change History (most recent first):
  20.                 7/22/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  21.                 
  22.  
  23. */
  24.  
  25. /////////////////////////////////////////////////////////////////////
  26. // The OT debugging macros in <OTDebug.h> require this variable to
  27. // be set.
  28.  
  29. #ifndef qDebug
  30. #define qDebug    1
  31. #endif
  32.  
  33. /////////////////////////////////////////////////////////////////////
  34. // Pick up all the standard OT stuff.
  35.  
  36. #include <OpenTransport.h>
  37.  
  38. /////////////////////////////////////////////////////////////////////
  39. // Pick up all the OT TCP/IP stuff.
  40.  
  41. #include <OpenTptInternet.h>
  42.  
  43. /////////////////////////////////////////////////////////////////////
  44. // Pick up all the OT serial stuff.
  45.  
  46. #include <OpenTptSerial.h>
  47.  
  48. /////////////////////////////////////////////////////////////////////
  49. // Pick up the OTDebugBreak and OTAssert macros.
  50.  
  51. #include <OTDebug.h>
  52.  
  53. /////////////////////////////////////////////////////////////////////
  54. // Standard C prototypes.
  55.  
  56. #include <stdio.h>
  57.  
  58. /////////////////////////////////////////////////////////////////////
  59. // OTDebugStr is not defined in any OT header files, but it is
  60. // exported by the libraries, so we define the prototype here.
  61.  
  62. extern pascal void OTDebugStr(const char* str);
  63.  
  64. /////////////////////////////////////////////////////////////////////
  65.  
  66. static OTResult SetFourByteOption(EndpointRef ep,
  67.                                     OTXTILevel level,
  68.                                     OTXTIName  name,
  69.                                     UInt32       value)
  70.     // level and name must denote a four byte option that is
  71.     // appropriate for the endpoint ep.  This routine sets the
  72.     // option to value.  ep is assumed to be in synchronous
  73.     // mode.
  74.     //
  75.     // If all goes well, the result is noErr.  If an error
  76.     // occurs, the result is negative.  If the option could not
  77.     // be negotiated, a positive result being one of (T_FAILURE,
  78.     // T_PARTSUCCESS, T_READONLY, T_NOTSUPPORT) is returned
  79. {
  80.     OTResult    err;
  81.     TOption        option;
  82.     TOptMgmt    request;
  83.     TOptMgmt    result;
  84.     
  85.     // Set up the option buffer to reflect the specific option
  86.     // and value we want to set.  We use a TOption structure
  87.     // to represent the option buffer.  TOption is specifically
  88.     // defined to allow easy construction of 4 byte options.
  89.     // If you want to negotiate different size options, or
  90.     // multiple options in a single call, then constructing
  91.     // the option buffer is a little trickier
  92.     
  93.     option.len        = kOTFourByteOptionSize;
  94.     option.level    = level;
  95.     option.name        = name;
  96.     option.status     = 0;
  97.     option.value[0] = value;
  98.  
  99.     // Set up the request for OTOptionManagement to point
  100.     // to the option buffer we just filled out, and tell
  101.     // it that we want to negotiate (ie set) the option.
  102.     
  103.     request.opt.buf    = (UInt8 *) &option;
  104.     request.opt.len    = sizeof(option);
  105.     request.flags    = T_NEGOTIATE;
  106.  
  107.     // Set up the reply for OTOptionManagement.  This is where
  108.     // OTOptionManagement puts the result of the negotiation.
  109.     
  110.     result.opt.buf = (UInt8 *) &option;
  111.     result.opt.maxlen = sizeof(option);
  112.  
  113.     // Call OTOptionManagement and then check that the value
  114.     // was negotiated successfully.  Any value other than
  115.     // T_SUCCESS is reported via the error result.
  116.     
  117.     err = OTOptionManagement(ep, &request, &result);
  118.  
  119.     if (err == noErr) {
  120.         if (option.status != T_SUCCESS) {
  121.             err = option.status;
  122.         }
  123.     }
  124.                 
  125.     return (err);
  126. }
  127.  
  128. /////////////////////////////////////////////////////////////////////
  129.  
  130. static OTResult GetFourByteOption(EndpointRef ep,
  131.                                     OTXTILevel level,
  132.                                     OTXTIName  name,
  133.                                     UInt32       *value)
  134.     // level and name must denote a four byte option that is
  135.     // appropriate for the endpoint ep.  This routine gets the
  136.     // current option setting and puts it in the the variable
  137.     // pointed to by value.  ep is assumed to be in synchronous
  138.     // mode.
  139.     //
  140.     // If all goes well, the result is noErr.  If an error
  141.     // occurs, the result is negative.  If the option could not
  142.     // be read, a positive result being one of (T_FAILURE,
  143.     // T_PARTSUCCESS, T_NOTSUPPORT) is returned
  144. {
  145.     OTResult    err;
  146.     TOption        option;
  147.     TOptMgmt    request;
  148.     TOptMgmt    result;
  149.     
  150.     // Set up the option buffer to reflect the specific option
  151.     // and value we want to set.  We use a TOption structure
  152.     // to represent the option buffer.  TOption is specifically
  153.     // defined to allow easy construction of 4 byte options.
  154.     // If you want to negotiate different size options, or
  155.     // multiple options in a single call, then constructing
  156.     // the option buffer is a little trickier
  157.     
  158.     option.len        = kOTFourByteOptionSize;
  159.     option.level    = level;
  160.     option.name        = name;
  161.     option.status     = 0;
  162.     option.value[0] = 0;    // Ignored because we're getting the value.
  163.  
  164.     // Set up the request for OTOptionManagement to point
  165.     // to the option buffer we just filled out, and tell
  166.     // it that we want to get the current value of the option.
  167.     
  168.     request.opt.buf    = (UInt8 *) &option;
  169.     request.opt.len    = sizeof(option);
  170.     request.flags    = T_CURRENT;
  171.  
  172.     // Set up the reply for OTOptionManagement.  This is where
  173.     // OTOptionManagement puts the result of the negotiation.
  174.     
  175.     result.opt.buf = (UInt8 *) &option;
  176.     result.opt.maxlen = sizeof(option);
  177.  
  178.     // Call OTOptionManagement and then check that the value
  179.     // was read successfully.  Any status other than
  180.     // T_SUCCESS or T_READONLY is reported via the error
  181.     // result.
  182.     
  183.     err = OTOptionManagement(ep, &request, &result);
  184.  
  185.     if (err == noErr) {
  186.         switch (option.status) {
  187.             case T_SUCCESS:
  188.             case T_READONLY:
  189.                 *value = option.value[0];
  190.                 break;
  191.             default:
  192.                 err = option.status;
  193.                 break;
  194.         }
  195.     }
  196.                 
  197.     return (err);
  198. }
  199.  
  200. /////////////////////////////////////////////////////////////////////
  201.  
  202. static OSStatus PrintOptionBuffer(const TNetbuf *optionBuffer)
  203.     // Print a summary of the optionBuffer to stdout.
  204.     // Basically the call enumerates the option buffer using
  205.     // OTNextOption, and prints the level, name, size and status
  206.     // of each of the options in the buffer.
  207. {
  208.     OSStatus err;
  209.     TOption    *currentOption;
  210.  
  211.     currentOption = nil;
  212.     do {
  213.         err = OTNextOption(optionBuffer->buf, optionBuffer->len, ¤tOption);
  214.         if (err == noErr && currentOption != nil) {
  215.             printf("Level = $%08x, Name = $%08x, Data Length = %d, Status = $%08x\n",
  216.                                 currentOption->level, 
  217.                                 currentOption->name, 
  218.                                 currentOption->len - kOTOptionHeaderSize,
  219.                                 currentOption->status);
  220.         }
  221.     } while (err == noErr && currentOption != nil);
  222.     
  223.     return (err);
  224. }
  225.  
  226. /////////////////////////////////////////////////////////////////////
  227.  
  228. static OSStatus PrintAllOptionsAtLevel(EndpointRef ep, OTXTILevel level)
  229.     // Gets all of the options for the endpoint ep at the specified
  230.     // level and prints a summary of them to stdout.
  231. {
  232.     OSStatus        err;
  233.     TEndpointInfo    epInfo;
  234.     TOptionHeader    requestOption;
  235.     void            *resultOptionBuffer;
  236.     TOptMgmt        request;
  237.     TOptMgmt        result;
  238.  
  239.     resultOptionBuffer = nil;
  240.  
  241.     // First call OTGetEndpointInfo to find out the maximum
  242.     // size of the options for this type of endpoint and then
  243.     // allocate that size buffer to hold the resulting options.
  244.     
  245.     err = OTGetEndpointInfo(ep, &epInfo);
  246.     if (err == noErr) {
  247.         resultOptionBuffer = OTAllocMem(epInfo.options);
  248.         if (resultOptionBuffer == nil) {
  249.             err = kENOMEMErr;
  250.         }
  251.     }
  252.     
  253.     // Call OTOptionManagement to get the current value (T_CURRENT)
  254.     // of all of the options (ie T_ALLOPT) of the specified level.
  255.     // The resulting options go into resultOptionBuffer, which we
  256.     // have just allocated.
  257.  
  258.     if (err == noErr) {
  259.         requestOption.len        = kOTOptionHeaderSize;
  260.         requestOption.level        = level;
  261.         requestOption.name        = T_ALLOPT;
  262.         requestOption.status     = 0;
  263.  
  264.         request.opt.buf    = (UInt8 *) &requestOption;
  265.         request.opt.len    = sizeof(requestOption);
  266.         request.flags    = T_CURRENT;
  267.         
  268.         result.opt.buf = resultOptionBuffer;
  269.         result.opt.maxlen = epInfo.options;
  270.         
  271.         err = OTOptionManagement(ep, &request, &result);
  272.     }
  273.     
  274.     // Now that we have the options, print them to stdout.
  275.     
  276.     if (err == noErr) {
  277.         err = PrintOptionBuffer(&result.opt);
  278.         printf("\n");
  279.     }
  280.     
  281.     // Clean up.
  282.     
  283.     if (resultOptionBuffer != nil) {
  284.         OTFreeMem(resultOptionBuffer);
  285.     }
  286.     
  287.     return (err);
  288. }
  289.  
  290. /////////////////////////////////////////////////////////////////////
  291.  
  292. static OSStatus PrintOptionsForConfiguration(const char *configStr, OTXTILevel level)
  293.     // Get all the options associated with a specific level of a specific
  294.     // OT provider (eg configStr) and then convert those options to a
  295.     // formatted string and output that string.
  296. {
  297.     OSStatus        err;
  298.     OSStatus        junk;
  299.     EndpointRef        ep;
  300.     TEndpointInfo    epInfo;
  301.     TOptionHeader    requestOption;
  302.     void            *resultOptionBuffer;
  303.     TOptMgmt        request;
  304.     TOptMgmt        result;
  305.     TOption            *resultOption;
  306.     char            optionsString[1024];
  307.  
  308.     resultOptionBuffer = nil;
  309.     ep = kOTInvalidEndpointRef;
  310.     
  311.     // First create an endpoint using the specified configuration.
  312.     // Note that we pass in epInfo to be filled out with the various
  313.     // parameters of this endpoint, including it's maximum option
  314.     // buffer size.
  315.     
  316.     ep = OTOpenEndpoint(OTCreateConfiguration(configStr), 0, &epInfo, &err);
  317.  
  318.     // Now allocate a buffer of the maximum option buffer size.
  319.     
  320.     if (err == noErr) {
  321.         resultOptionBuffer = OTAllocMem(epInfo.options);
  322.         if (resultOptionBuffer == nil) {
  323.             err = kENOMEMErr;
  324.         }
  325.     }
  326.  
  327.     // Call OTOptionManagement to get the current value (T_CURRENT)
  328.     // of all of the options (ie T_ALLOPT) of the specified level.
  329.     // The resulting options go into resultOptionBuffer, which we
  330.     // have just allocated.
  331.  
  332.     if (err == noErr) {
  333.         requestOption.len        = kOTOptionHeaderSize;
  334.         requestOption.level        = level;
  335.         requestOption.name        = T_ALLOPT;
  336.         requestOption.status     = 0;
  337.  
  338.         request.opt.buf    = (UInt8 *) &requestOption;
  339.         request.opt.len    = sizeof(requestOption);
  340.         request.flags    = T_CURRENT;
  341.         
  342.         result.opt.buf = resultOptionBuffer;
  343.         result.opt.maxlen = epInfo.options;
  344.         
  345.         err = OTOptionManagement(ep, &request, &result);
  346.     }
  347.     
  348.     // Now use OTCreateOptionString to convert the resulting
  349.     // buffer full of options into a formatted string, and then print
  350.     // that formatted string to stdout.
  351.     
  352.     if (err == noErr) {
  353.         resultOption = (TOption *) result.opt.buf;
  354.         err = OTCreateOptionString(configStr, &resultOption, result.opt.buf + result.opt.len, optionsString, 1024);
  355.         if (err == noErr) {
  356.             printf("Formatted Options = “%s”\n\n", optionsString);
  357.         }
  358.     }
  359.     
  360.     // Clean up.
  361.     
  362.     if (resultOptionBuffer != nil) {
  363.         OTFreeMem(resultOptionBuffer);
  364.     }
  365.     if (ep != kOTInvalidEndpointRef) {
  366.         junk = OTCloseProvider(ep);
  367.         OTAssert("PrintOptionsForConfiguration: Closing the endpoint failed", junk == noErr);
  368.     }
  369.     
  370.     return (err);
  371. }
  372.  
  373. /////////////////////////////////////////////////////////////////////
  374.  
  375. static OSStatus BuildAndPrintOptions(const char *configStr, const char *optionsString)
  376.     // Given a configuration string and a set of formatted options, converts
  377.     // the options to their binary format (ie an options buffer) and then
  378.     // prints that buffer to stdout.
  379. {
  380.     OSStatus err;
  381.     OSStatus junk;
  382.     void *resultOptionBuffer;
  383.     EndpointRef ep;
  384.     TEndpointInfo epInfo;
  385.     TNetbuf optionsNetbuf;
  386.     
  387.     resultOptionBuffer = nil;
  388.     ep = kOTInvalidEndpointRef;
  389.     
  390.     // First create an endpoint using the specified configuration.
  391.     // Note that we pass in epInfo to be filled out with the various
  392.     // parameters of this endpoint, including it's maximum option
  393.     // buffer size.
  394.  
  395.     ep = OTOpenEndpoint(OTCreateConfiguration(configStr), 0, &epInfo, &err);
  396.     
  397.     // Now allocate a buffer of the maximum option buffer size.
  398.  
  399.     if (err == noErr) {
  400.         resultOptionBuffer = OTAllocMem(epInfo.options);
  401.         if (resultOptionBuffer == nil) {
  402.             err = kENOMEMErr;
  403.         }
  404.     }
  405.  
  406.     // Call OTCreateOptions to parse the formatted optionsString into
  407.     // the binary format (optionsNetbuf), and then use PrintOptionBuffer
  408.     // to output that buffer to stdout.
  409.  
  410.     if (err == noErr) {
  411.         optionsNetbuf.buf = resultOptionBuffer;
  412.         optionsNetbuf.len = 0;
  413.         optionsNetbuf.maxlen = epInfo.options;
  414.         err = OTCreateOptions(configStr, (char **) &optionsString, &optionsNetbuf);
  415.         
  416.         if (err == noErr) {
  417.             err = PrintOptionBuffer(&optionsNetbuf);
  418.             printf("\n");
  419.         }
  420.     }
  421.     
  422.     // Clean up.
  423.     
  424.     if (resultOptionBuffer != nil) {
  425.         OTFreeMem(resultOptionBuffer);
  426.     }
  427.     if (ep != kOTInvalidEndpointRef) {
  428.         junk = OTCloseProvider(ep);
  429.         OTAssert("BuildAndPrintOptions: Closing the endpoint failed", junk == noErr);
  430.     }
  431.     
  432.     return (err);
  433. }
  434.  
  435. /////////////////////////////////////////////////////////////////////
  436.  
  437. void main(void)
  438.     // A simple main line that demonstrates the use of the various
  439.     // functions defined above.  The basic idea is to create
  440.     // an endpoint, get the value of the IP_REUSEADDR option, then
  441.     // change it to true, and read it back to verify that the change
  442.     // worked.  We then do a few other interesting things with
  443.     // various miscellaneous options API routines.
  444. {
  445.     OSStatus err;
  446.     OSStatus junk;
  447.     EndpointRef ep;
  448.     UInt32 value;
  449.     
  450.     printf("Hello Cruel World!\n");
  451.     
  452.     err = InitOpenTransport();
  453.     
  454.     if (err == noErr) {
  455.     
  456.         ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, nil, &err);
  457.         if (err == noErr) {
  458.             
  459.             printf("\nGetting and Setting IP_REUSEADDR.\n");
  460.             
  461.             err = GetFourByteOption(ep, INET_IP, IP_REUSEADDR, &value);
  462.             if (err == noErr) {
  463.                 printf("Default value = %d\n", value);
  464.             }
  465.             if (err == noErr) {
  466.                 err = SetFourByteOption(ep, INET_IP, IP_REUSEADDR, true);
  467.             }
  468.             if (err == noErr) {
  469.                 err = GetFourByteOption(ep, INET_IP, IP_REUSEADDR, &value);
  470.                 if (err == noErr) {
  471.                     printf("New value = %d\n", value);
  472.                 }
  473.             }
  474.  
  475.             if (err == noErr) {
  476.                 printf("\nPrinting Options Piecemeal at Level INET_IP.\n");
  477.                 err = PrintAllOptionsAtLevel(ep, INET_IP);
  478.             }
  479.             
  480.             if (err == noErr) {
  481.                 printf("\nPrinting Formatted Options at Level COM_SERIAL.\n");
  482.                 err = PrintOptionsForConfiguration(kSerialName, COM_SERIAL);
  483.             }
  484.             
  485.             if (err == noErr) {
  486.                 printf("\nBuilding Options for COM_SERIAL.\n");
  487.                 err = BuildAndPrintOptions(kSerialName, "BaudRate=9600, DataBits=7, StopBits=15");
  488.             }
  489.             
  490.             junk = OTCloseProvider(ep);
  491.             OTAssert("GetSetOptions: Closing the endpoint failed", junk == noErr);
  492.         }
  493.         
  494.         CloseOpenTransport();
  495.     }
  496.     
  497.     if (err == noErr) {
  498.         printf("Success.\n");
  499.     } else {
  500.         printf("Failed with error %d.\n", err);
  501.     }
  502.     printf("Done.  Press command-Q to Quit.\n");
  503. }
  504.  
  505.  
  506.